package org.az.netty_study.p11_netty的黏包与半包;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufAllocator;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.embedded.EmbeddedChannel;
import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;

/**
 * LTC，一般指一条消息中，除了真实数据外带有额外内容的消息
 * 比如下面的例子
 *   +--------+----------------+
 *   | Length | Actual Content |
 *   | 0x000C | "HELLO, WORLD" |
 *   +--------+----------------+
 * 发送的数据，分为两个部分，根据长度字段可以获取后面的真实数据
 *  - 长度字段:真实数据的长度
 *  - 真实数据
 * 当然，也可以包含其他额外内容
 *   +------+--------+------+----------------+      +------+----------------+
 *   | HDR1 | Length | HDR2 | Actual Content |----->| HDR2 | Actual Content |
 *   | 0xCA | 0x000C | 0xFE | "HELLO, WORLD" |      | 0xFE | "HELLO, WORLD" |
 *   +------+--------+------+----------------+      +------+----------------+
 */
public class _6_黏包半包的解决之LTC解码器 {
    public static void main(String[] args) {
        /**
         * netty提供的LTC解码器叫LengthFieldBasedFrameDecoder，有5个参数
         *  1.maxFrameLength:最大消息长度
         *  2.lengthFieldOffset:长度字段的偏移量
         *  3.lengthFieldLength:长度字段本身占据的字节长度
         *  4.lengthAdjustment:长度字段再往后多少个字节才是真实数据开始的地方
         *  5.initialBytesToStrip:从消息中剥离头几个字节(因为服务器使用消息时，不想看到真实数据外的额外内容，一般将额外内容剥离)
         */
        EmbeddedChannel channel = new EmbeddedChannel(
                //lengthFieldLength是4，是因为int的长度为4个字节
                new LengthFieldBasedFrameDecoder(1024, 0, 4, 0, 4),
                new LoggingHandler(LogLevel.DEBUG)
        );

        ByteBuf buf = ByteBufAllocator.DEFAULT.buffer();
        sendMsg(buf, "hello world");
        sendMsg(buf, "hahahahah");
        sendMsg(buf, "how are you?");
        channel.writeInbound(buf);
    }

    private static void sendMsg(ByteBuf buf, String msg) {
        byte[] bytes = msg.getBytes();
        buf.writeInt(bytes.length);
        buf.writeBytes(bytes);
    }
}
